{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# 直方图 (Histogram) 教程\n",
        "\n",
        "本部分将详细讲解如何使用 Matplotlib 绘制直方图，包括基础直方图的绘制、直方图的定制选项以及多组直方图的应用。\n",
        "\n",
        "## 学习内容\n",
        "1. **基础直方图**\n",
        "   - `plt.hist(x, bins)` 绘制直方图\n",
        "   - `bins`：分组数量或分组边界\n",
        "   - `range`：数据范围\n",
        "   - `density`：是否归一化（显示概率密度）\n",
        "\n",
        "2. **直方图定制**\n",
        "   - `color`：颜色\n",
        "   - `alpha`：透明度\n",
        "   - `edgecolor`：边框颜色\n",
        "   - `orientation`：方向（`'vertical'`, `'horizontal'`）\n",
        "   - `cumulative`：累积直方图\n",
        "\n",
        "3. **多组直方图**\n",
        "   - 重叠直方图：多次调用 `plt.hist()`\n",
        "   - 并排直方图：使用 `alpha` 和位置偏移\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 导入必要的库\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "# 设置中文字体（如果需要显示中文）\n",
        "plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Arial Unicode MS']\n",
        "plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题\n",
        "\n",
        "# 在 Jupyter Notebook 中内联显示图形\n",
        "%matplotlib inline\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 第一部分：基础直方图\n",
        "\n",
        "直方图用于展示数据的分布情况，将数据分成若干个区间（bins），统计每个区间内数据的频数或频率。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.1 plt.hist(x, bins) 绘制直方图\n",
        "\n",
        "`plt.hist(x, bins)` 是绘制直方图的基础函数。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, bins)\n",
        "```\n",
        "\n",
        "**参数说明**：\n",
        "- `x`：输入数据（数组或列表）\n",
        "- `bins`：分组数量（整数）或分组边界（数组）\n",
        "- `range`：数据范围，格式为 `(min, max)`\n",
        "- `density`：是否归一化，`True` 显示概率密度，`False` 显示频数（默认）\n",
        "- `cumulative`：是否显示累积直方图（默认 `False`）\n",
        "\n",
        "**返回值**：\n",
        "- `n`：每个区间的频数或密度值\n",
        "- `bins`：区间的边界值\n",
        "- `patches`：图形对象列表\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 1：基础直方图\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)  # 生成正态分布数据，均值100，标准差15\n",
        "\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(data, bins=30)\n",
        "plt.title('基础直方图示例', fontsize=14)\n",
        "plt.xlabel('数值', fontsize=12)\n",
        "plt.ylabel('频数', fontsize=12)\n",
        "plt.grid(True, alpha=0.3, axis='y')\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.2 bins 参数：分组数量或分组边界\n",
        "\n",
        "`bins` 参数控制如何将数据分组，可以是：\n",
        "- **整数**：指定分组数量，自动计算分组边界\n",
        "- **数组**：指定分组边界\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, bins=30)  # 分成30组\n",
        "plt.hist(x, bins=[0, 10, 20, 30, 40, 50])  # 指定分组边界\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 2：不同 bins 设置\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n",
        "\n",
        "# 少量分组\n",
        "axes[0].hist(data, bins=10, color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('少量分组 (bins=10)', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 中等分组\n",
        "axes[1].hist(data, bins=30, color='steelblue', edgecolor='black')\n",
        "axes[1].set_title('中等分组 (bins=30)', fontsize=12)\n",
        "axes[1].set_xlabel('数值', fontsize=10)\n",
        "axes[1].set_ylabel('频数', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 大量分组\n",
        "axes[2].hist(data, bins=100, color='steelblue', edgecolor='black')\n",
        "axes[2].set_title('大量分组 (bins=100)', fontsize=12)\n",
        "axes[2].set_xlabel('数值', fontsize=10)\n",
        "axes[2].set_ylabel('频数', fontsize=10)\n",
        "axes[2].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n",
        "\n",
        "# 示例 3：指定分组边界\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "bins = np.arange(50, 151, 10)  # 从50到150，每10一组\n",
        "\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(data, bins=bins, color='steelblue', edgecolor='black')\n",
        "plt.title('指定分组边界的直方图', fontsize=14)\n",
        "plt.xlabel('数值', fontsize=12)\n",
        "plt.ylabel('频数', fontsize=12)\n",
        "plt.grid(True, alpha=0.3, axis='y')\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.3 density 参数：归一化显示\n",
        "\n",
        "`density` 参数控制是否将直方图归一化，显示概率密度而不是频数。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, density=True)  # 显示概率密度\n",
        "plt.hist(x, density=False)  # 显示频数（默认）\n",
        "```\n",
        "\n",
        "**区别**：\n",
        "- `density=False`：y 轴显示频数（每个区间的数据点数量）\n",
        "- `density=True`：y 轴显示概率密度（面积总和为1）\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 4：density 参数对比\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
        "\n",
        "# 显示频数\n",
        "axes[0].hist(data, bins=30, density=False, color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('显示频数 (density=False)', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 显示概率密度\n",
        "axes[1].hist(data, bins=30, density=True, color='coral', edgecolor='black')\n",
        "axes[1].set_title('显示概率密度 (density=True)', fontsize=12)\n",
        "axes[1].set_xlabel('数值', fontsize=10)\n",
        "axes[1].set_ylabel('概率密度', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 第二部分：直方图定制\n",
        "\n",
        "直方图支持丰富的定制选项，可以控制颜色、透明度、边框等。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.1 颜色、透明度和边框\n",
        "\n",
        "直方图支持颜色、透明度和边框的定制。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, color='steelblue', alpha=0.7, edgecolor='black')\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 5：颜色、透明度和边框\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n",
        "\n",
        "# 不同颜色\n",
        "axes[0].hist(data, bins=30, color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('不同颜色', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 透明度\n",
        "axes[1].hist(data, bins=30, color='coral', alpha=0.6, edgecolor='black')\n",
        "axes[1].set_title('透明度 (alpha=0.6)', fontsize=12)\n",
        "axes[1].set_xlabel('数值', fontsize=10)\n",
        "axes[1].set_ylabel('频数', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 无边框\n",
        "axes[2].hist(data, bins=30, color='green', edgecolor='none')\n",
        "axes[2].set_title('无边框', fontsize=12)\n",
        "axes[2].set_xlabel('数值', fontsize=10)\n",
        "axes[2].set_ylabel('频数', fontsize=10)\n",
        "axes[2].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.2 orientation 参数：水平直方图\n",
        "\n",
        "`orientation` 参数控制直方图的方向。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, orientation='vertical')  # 垂直（默认）\n",
        "plt.hist(x, orientation='horizontal')  # 水平\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 6：水平直方图\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
        "\n",
        "# 垂直直方图\n",
        "axes[0].hist(data, bins=30, orientation='vertical', color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('垂直直方图', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 水平直方图\n",
        "axes[1].hist(data, bins=30, orientation='horizontal', color='coral', edgecolor='black')\n",
        "axes[1].set_title('水平直方图', fontsize=12)\n",
        "axes[1].set_xlabel('频数', fontsize=10)\n",
        "axes[1].set_ylabel('数值', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='x')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.3 cumulative 参数：累积直方图\n",
        "\n",
        "`cumulative` 参数用于显示累积直方图，展示小于等于某个值的数据比例。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(x, cumulative=True)  # 累积直方图\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 7：累积直方图\n",
        "np.random.seed(42)\n",
        "data = np.random.normal(100, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
        "\n",
        "# 普通直方图\n",
        "axes[0].hist(data, bins=30, color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('普通直方图', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "# 累积直方图\n",
        "axes[1].hist(data, bins=30, cumulative=True, color='coral', edgecolor='black')\n",
        "axes[1].set_title('累积直方图', fontsize=12)\n",
        "axes[1].set_xlabel('数值', fontsize=10)\n",
        "axes[1].set_ylabel('累积频数', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 第三部分：多组直方图\n",
        "\n",
        "可以同时绘制多个数据组的直方图，用于比较不同数据集的分布。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.1 重叠直方图\n",
        "\n",
        "重叠直方图通过多次调用 `plt.hist()` 实现，使用 `alpha` 参数让重叠部分可见。\n",
        "\n",
        "**基本语法**：\n",
        "```python\n",
        "plt.hist(data1, bins=30, alpha=0.6, label='组1')\n",
        "plt.hist(data2, bins=30, alpha=0.6, label='组2')\n",
        "plt.legend()\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 8：重叠直方图\n",
        "np.random.seed(42)\n",
        "data1 = np.random.normal(100, 15, 1000)  # 第一组数据\n",
        "data2 = np.random.normal(110, 15, 1000)  # 第二组数据\n",
        "\n",
        "plt.figure(figsize=(10, 6))\n",
        "plt.hist(data1, bins=30, alpha=0.6, label='组1', color='steelblue', edgecolor='black')\n",
        "plt.hist(data2, bins=30, alpha=0.6, label='组2', color='coral', edgecolor='black')\n",
        "plt.title('重叠直方图：两组数据分布对比', fontsize=14)\n",
        "plt.xlabel('数值', fontsize=12)\n",
        "plt.ylabel('频数', fontsize=12)\n",
        "plt.legend(fontsize=11)\n",
        "plt.grid(True, alpha=0.3, axis='y')\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.2 并排直方图\n",
        "\n",
        "并排直方图通过调整 bins 的位置实现，让不同组的数据并排显示。\n",
        "\n",
        "**实现方法**：\n",
        "1. 计算每组数据的 bins 位置偏移\n",
        "2. 分别绘制每组数据\n",
        "3. 调整 x 轴标签\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例 9：并排直方图（使用 subplot）\n",
        "np.random.seed(42)\n",
        "data1 = np.random.normal(100, 15, 1000)\n",
        "data2 = np.random.normal(110, 15, 1000)\n",
        "\n",
        "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
        "\n",
        "axes[0].hist(data1, bins=30, color='steelblue', edgecolor='black')\n",
        "axes[0].set_title('组1', fontsize=12)\n",
        "axes[0].set_xlabel('数值', fontsize=10)\n",
        "axes[0].set_ylabel('频数', fontsize=10)\n",
        "axes[0].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "axes[1].hist(data2, bins=30, color='coral', edgecolor='black')\n",
        "axes[1].set_title('组2', fontsize=12)\n",
        "axes[1].set_xlabel('数值', fontsize=10)\n",
        "axes[1].set_ylabel('频数', fontsize=10)\n",
        "axes[1].grid(True, alpha=0.3, axis='y')\n",
        "\n",
        "plt.suptitle('并排直方图：两组数据分布对比', fontsize=14)\n",
        "plt.tight_layout()\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 总结\n",
        "\n",
        "本教程详细介绍了 Matplotlib 直方图的绘制方法，包括：\n",
        "\n",
        "1. **基础直方图**：使用 `plt.hist(x, bins)` 绘制，支持 bins、range、density 等参数\n",
        "2. **直方图定制**：颜色、透明度、边框、方向、累积等选项\n",
        "3. **多组直方图**：重叠直方图和并排直方图的实现方法\n",
        "\n",
        "**关键要点**：\n",
        "- 直方图用于展示数据的分布情况\n",
        "- `bins` 参数控制分组数量或分组边界\n",
        "- `density=True` 显示概率密度，`density=False` 显示频数\n",
        "- 使用 `alpha` 参数可以让重叠的直方图可见\n",
        "- 累积直方图可以展示数据的累积分布\n"
      ]
    }
  ],
  "metadata": {
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
